package handlers

import (
	"fmt"
	"time"

	"sales-web/server/config"

	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt"
)

type UserJwtInfo struct {
	ID        int64     `json:"id"`
	Username  string    `json:"username"`
	Nickname  string    `json:"nickname"`
	Email     string    `json:"email"`
	Role      string    `json:"role"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

const JwtCookieName = "user_jwt"

type UserJwtClaim struct {
	jwt.StandardClaims
	User *UserJwtInfo `json:"user"`
}

func CreateUserJwt(user *UserJwtInfo, expireAt int64) (string, error) {

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, UserJwtClaim{
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: expireAt,
		},
		User: user,
	})
	tokenString, err := token.SignedString([]byte(config.GetGlobalCfg().AuthKey))
	return tokenString, err
}

func ParseUserJwt(tokenString string) (*UserJwtInfo, error) {
	var userJwtClaim UserJwtClaim
	token, err := jwt.ParseWithClaims(tokenString, &userJwtClaim, func(token *jwt.Token) (interface{}, error) {
		return []byte(config.GetGlobalCfg().AuthKey), nil
	})
	if err != nil {
		return nil, err
	}
	if !token.Valid {
		return nil, err
	}
	return userJwtClaim.User, nil
}

func JwtAuth() gin.HandlerFunc {
	return func(c *gin.Context) {
		jwtString, err := c.Request.Cookie(JwtCookieName)
		if err != nil {
			SendErrResp(c, 401, fmt.Errorf("failed to get user jwt err:%s", err))
			c.Abort()
			return
		}
		user, err := ParseUserJwt(jwtString.Value)
		if err != nil {
			SendErrResp(c, 401, fmt.Errorf("failed to parse user jwt err:%s", err))
			c.Abort()
			return
		}
		c.Set("user", user)
		c.Next()
	}
}

func GetCurrentUser(c *gin.Context) *UserJwtInfo {
	val, exists := c.Get("user")
	if exists {
		return val.(*UserJwtInfo)
	}
	return nil
}
